package org.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.commonapi.domain.Practice;
import org.example.commonapi.domain.R;
import org.example.commonapi.domain.SchoolAccount;
import org.example.commonapi.domain.Suggestion;
import org.example.commonapi.domain.User;
import org.example.commonapi.domain.Video;
import org.example.commonapi.dto.LoginInfo;
import org.example.commonapi.dto.SchoolAccountDto;
import org.example.commonapi.util.JwtUtil;
import org.example.commonapi.util.StringUtil;
import org.example.commonapi.util.oss.OssService;
import org.example.commonapi.util.redis.RedisService;
import org.example.commonapi.util.redis.UserPrefix;
import org.example.commonapi.vo.CourseVO;
import org.example.commonapi.vo.SchoolAccountVO;
import org.example.commonapi.vo.StatisticVO;
import org.example.commonapi.vo.VideoVO;
import org.example.service.AdminService;
import org.example.service.CourseService;
import org.example.service.SchoolAccountService;
import org.example.service.UserService;
import org.example.service.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/admin")
public class AdminController {

    @Resource
    private SchoolAccountService accountService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private OssService ossService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private VideoService videoService;

    @Autowired
    private AdminService adminService;

    /**
     * 管理员登陆
     * @param loginInfo
     * @return
     */
    @PostMapping("/login")
    public R login(@RequestBody LoginInfo loginInfo) {
        // 获取用户名+密码
        String username=loginInfo.getUsername();
        String password=loginInfo.getPassword();
        log.info("当前登录用户为{}",username);
        if(StringUtil.isAnyEmpty(username,password))return R.error("用户名或密码不能为空");
        // 从数据库搜索
        User user = adminService.login(username,password);
        if(user ==null)
            return R.error("用户名或密码错误");
        if(user.getRole() != 4 && user.getRole() != 3) {
            return R.error("用户权限不足");
        }
        String token=setToken(user);
        return R.success(token);
    }

    /**
     * 管理员注册
     * @param loginInfo
     * @return
     */
    @PostMapping("/register")
    public R register(@RequestBody LoginInfo loginInfo) {
        //多参数判空
        if(StringUtil.isAnyEmpty(loginInfo.getUsername(),loginInfo.getPassword()))
            return R.error("用户名或密码不能为空");
        //用户已存在
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,loginInfo.getUsername());
        if(userService.exists(queryWrapper)) return R.error("用户名已存在");
        Long id = adminService.register(loginInfo);
        loginInfo.setId(id);
        String token=setToken(new User(loginInfo));
        log.info("注册成功,当前注册用户为{}",loginInfo.getUsername());
        return R.success(token);
    }

    /**
     * 退出登录
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public R logout(HttpServletRequest request){
        LoginInfo loginInfo=jwtUtil.parseJwt(request.getHeader("token"));
        log.info("退出登录，退出的用户为{}",loginInfo);
        redisService.del(UserPrefix.userKeyById,String.valueOf(loginInfo.getId()));
        return R.success();
    }

    /**
     * 放用户信息到redis中并生成token
     * @param user
     * @return
     */
    public String setToken(User user) {
//      创建token,返回token
        String token = jwtUtil.createJwt(new LoginInfo(user));
//      放入redis中
        redisService.set(UserPrefix.userKeyById, String.valueOf(user.getId()), token, 7 * 24 * 60 * 60 * 60);
//        生成的token
        log.info("生成的token:{}",token);
        return token;
    }

    /**
     * 学校账号提交审核信息
     * @return
     */
    @PostMapping("/submitInfomation")
    public R submitInformation(@RequestBody SchoolAccountDto schoolAccountDto, HttpServletRequest request) {
        if ( schoolAccountDto.getSchoolName() == null || schoolAccountDto.getSchoolName().isEmpty()) {
            return R.error("请输入学校名称");
        }
        if ( schoolAccountDto.getProofImg() == null || schoolAccountDto.getProofImg().isEmpty()) {
            return R.error("请上传学校证明");
        }
        return accountService.submitInformation(schoolAccountDto,request);
    }

    /**
     * 获取所有审核中的审核请求
     * @return
     */
    @GetMapping("/getSchoolCheckInformation")
    public R<List<SchoolAccountVO>> getSchoolCheckInformation() {
        return accountService.getSchoolCheckInformation();
    }

    /**
     * 管理员通过学校审核
     * @param id
     * @return
     */
    @PutMapping("/passSchoolCheckInformation")
    public R passSchoolCheckInformation(@RequestParam Integer id) {
        return accountService.passSchoolCheckInformation(id);
    }

    /**
     * 管理员拒绝学校审核
     * @param id
     * @param reason
     * @return
     */
    @PutMapping("/refuseSchoolCheckInformation")
    public R refuseSchoolCheckInformation(@RequestParam Integer id,@RequestParam String reason) {
        if ( reason == null || reason.isEmpty()) {
            return R.error("请输入拒绝理由");
        }
        return accountService.refuseSchoolCheckInformation(id,reason);
    }

    /**
     * 获取当前登录用户提交的审核的信息
     * @param request
     * @return
     */
    @GetMapping("/getNowUserSubmitInfo")
    public R<SchoolAccount> getNowUserSubmitInfo(HttpServletRequest request) {
        return accountService.getNowUserSubmitInfo(request);
    }

    /**
     * 获取当前用户信息
     * @param request
     * @return
     */
    @GetMapping("/getNowUserInfo")
    public R<User> getNowUserInfo(HttpServletRequest request) {
        return adminService.getNowUserInfo(request);
    }

    /**
     * 上传文件接口
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public R<String> upload(@RequestParam("file") MultipartFile file) {
        String upload = ossService.upload(file);
        return R.success(upload);
    }

    /**
     * 学校账号获取所有本学校的用户 根据role查询学生或者教师
     * @param request
     * @param role
     * @return
     */
    @GetMapping("/schoolGetUserInfo")
    public R<List<User>> schoolGetUserInfo(HttpServletRequest request,@RequestParam Integer role) {
        return adminService.schoolGetUserInfo(request,role);
    }

    /**
     * 管理员获取所有用户的信息
     * @return
     */
    @GetMapping("/adminGetUserInfo")
    public R<List<User>> adminGetUserInfo(@RequestParam Integer role) {
        return adminService.adminGetUserInfo(role);
    }

    /**
     * 学校账号获取所有的课程信息
     * @param request
     * @return
     */
    @GetMapping("/schoolGetCourseInfo")
    public R<List<CourseVO>> schoolGetCourseInfo(HttpServletRequest request){
        return adminService.schoolGetCourseInfo(request);
    }

    /**
     * 管理员获取所有课程信息
     * @return
     */
    @GetMapping("/adminGetCourseInfo")
    public R<List<CourseVO>> adminGetCourseInfo(){
        return adminService.adminGetCourseInfo();
    }

    /**
     * 学校账号获取本学校发布的所有视频
     * @param request
     * @return
     */
    @GetMapping("/schoolGetVideoInfo")
    public R<List<VideoVO>> schoolGetVideoInfo(HttpServletRequest request){
        return adminService.schoolGetVideoInfo(request);
    }

    /**
     * 管理员获取所有视频信息
     * @return
     */
    @GetMapping("/adminGetVideoInfo")
    public R<List<VideoVO>> adminGetVideoInfo(){
        return adminService.adminGetVideoInfo();
    }

    /**
     * 获取本学校播放量最高的8个视频
     * @return
     */
    @GetMapping("/getMaxPlayCountVideo")
    public R<List<Video>> getMaxPlayCountVideo(HttpServletRequest request,@RequestParam Integer role){
        return adminService.getMaxPlayCountVideo(request,role);
    }

    /**
     * 获取本学校访问量排行前8的题目
     * @param request
     * @return
     */
    @GetMapping("/getMaxVisitPractice")
    public R<List<Practice>> getMaxVisitPractice(HttpServletRequest request,@RequestParam Integer role){
        return adminService.getMaxVisitPractice(request,role);
    }

    /**
     * 获取今日按每隔3小时分割用户活跃度
     * @param request
     * @return
     */
    @GetMapping("/getTodayUserInfo")
    public R<List<Integer>> getTodayUserInfo(HttpServletRequest request,@RequestParam Integer role){
        return adminService.getTodayUserInfo(request,role);
    }

    /**
     * 计算相关统计数据
     * @param request
     * @param role
     * @return
     */
    @GetMapping("/getStatisticData")
    public R<List<StatisticVO>> getStatisticData(HttpServletRequest request, @RequestParam Integer role){
        return adminService.getStatisticData(request,role);
    }

    /**
     * 导入名单
     * @param request
     * @param file
     * @param role
     * @return
     * @throws IOException
     */
    @PostMapping("/importExcelUser")
    public R importExcelUser(HttpServletRequest request,@RequestParam("file") MultipartFile file,@RequestParam("role") Integer role) throws IOException {
        return adminService.importExcelUser(request,file,role);
    }

    /**
     * 每天11:59时执行该定时方法 更新redis数据
     */
    @Scheduled(cron = "59 59 11 * * ?")
    private void updateStatistic() {
        adminService.updateStatistic();
    }

    /**
     * 获取所有用户反馈
     * @return
     */
    @GetMapping("/getUserSuggestion")
    public R<List<Suggestion>> getUserSuggestion(){
        return adminService.getUserSuggestion();
    }
}
